

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TrackSystem.Entities.Extensions;
using TrackSystem.IO.Alarm;
using TrackSystem.IO.Data;
using TrackSystem.IO.Models;
using TrackSystem.IO.Utils;

namespace TrackSystem.IO.Protocol
{
    /// <summary>
    /// PTZ相机控制协议
    ///0, motor stop
    ///1, tilt up
    ///2, tilt down
    ///3, pan left
    ///4, pan right
    ///5, zoom out
    ///6, zoom in
    ///7, focus near
    ///8, focus far
    ///9, iris down
    ///10, iris up
    ///11, 0-continue, 1-step
    ///12, speed 0-63
    ///13, 1- login 2-logout
    ///14, clear queue
    /// </summary>
    public class PTZCamProtocol : ProtocolBase
    {
        private int startTicks;
        private int repeatTimes;    //写入操作重复次数

        private readonly int rwLength;
        private bool bSendW;     // 发送标志

        private string camIp;
        private int camPort;
        private string camAdmin;
        private string camPassword;
        private PTZCamControl camController;
        bool islogin;
        uint step;
        uint nspeed;
        

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="admin"></param>
        /// <param name="password"></param>
        /// <param name="rwLength"></param>
        public PTZCamProtocol(string name, string ip, int port)
            : base()
        {
            this.Name = name;
            this.camIp = ip;
            this.camPort = port;
            this.camAdmin = "admin";
            this.camPassword = "cmi@1872";
            this.islogin = false;
            camController = new PTZCamControl(camIp, camPort, camAdmin, camPassword);
            NeedInit = true;
        }

        /// <summary>
        /// 生成读取寄存器的通讯帧
        /// </summary>
        /// <returns></returns>
        public override byte[] GenerateReadFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            if (!islogin)
            {
                Fail_R++;
            }
            else
            {
                Succ_R++;
                Fail_R = 0;
            }
            if (NeedInit && !islogin && Fail_R > 900 && Fail_R % 50 == 0 && Fail_R < 1000) //只登录1次
            { // 延迟90秒后开始尝试登录,100秒后不再尝试（转为发送指令尝试）,连续尝试登录会导致线程错误(登录3次不成功会发生错误)
                try
                {
                    islogin = camController.login();
                    if (islogin)
                    {
                        RegFactory.Instance.SetVal(RegNameList[11], 0); // 1-step, 0-continue 
                        RegFactory.Instance.SetVal(RegNameList[12], 30); // speed default = 30
                        NeedInit = false;
                        Fail_R = 0;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
            if (Fail_R >= 10)
            {
                Succ_R = 0;
            }
            NeedRecvLen = 0;
            return null;
        }


        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessReadFrame(byte[] buffer)
        {
            Rx_r = buffer;
            Lapse = Environment.TickCount - startTicks;
            return true;
        }

        /// <summary>
        /// 生成写入寄存器的通讯帧
        /// </summary>
        /// <param name="NeedRecvLen"></param>
        /// <returns></returns>
        public override byte[] GenerateWriteFrame(out int NeedRecvLen)
        {
            // 待写入的数据队列非空 
            if (writeQueue.Count() > 0)
            {
                repeatTimes = 3;    // 写入的重复次数更新为3次
            }
            this.nspeed = (uint)RegFactory.Instance.GetVal(RegNameList[12]).iVal;
            this.step = (uint)RegFactory.Instance.GetVal(RegNameList[12]).iVal;
            if (WriteFlag && repeatTimes-- > 0)
            {
                bSendW = false;
                startTicks = Environment.TickCount;
                while (writeQueue.TryDequeue(out AddressAndVal data))
                {
                    if (data.Address == 0 && data.Value == 1)
                    {
                        camController.CamControl(0x3000, step, nspeed); // zoom wide
                    }else if (data.Address == 1 && data.Value == 1)
                    {
                        camController.CamControl(0x3001, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 2 && data.Value == 1)
                    {
                        camController.CamControl(0x3002, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 3 && data.Value == 1)
                    {
                        camController.CamControl(0x3003, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 4 && data.Value == 1)
                    {
                        camController.CamControl(0x3004, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 5 && data.Value == 1)
                    {
                        camController.CamControl(0x3005, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 6 && data.Value == 1)
                    {
                        camController.CamControl(0x3006, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 7 && data.Value == 1)
                    {
                        camController.CamControl(0x3007, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 8 && data.Value == 1)
                    {
                        camController.CamControl(0x3008, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 9 && data.Value == 1)
                    {
                        camController.CamControl(0x3009, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 10 && data.Value == 1)
                    {
                        camController.CamControl(0x3010, step, nspeed); // zoom wide
                    }
                    else if (data.Address == 11)
                    {
                        RegFactory.Instance.SetVal(RegNameList[11], data.Value); // 1-step, 0-continue 
                    }
                    else if (data.Address == 12)
                    {
                        RegFactory.Instance.SetVal(RegNameList[12], data.Value); //// speed default = 30
                    }
                    RegFactory.Instance.SetVal(RegNameList[data.Address], data.Value);
                    bSendW = true;
                }
                if (bSendW)
                {
                    WriteFlag = false;
                    Succ_W++;
                    Fail_W = 0;
                }
                else
                {
                    Fail_W++;
                }
                Lapse = Environment.TickCount - startTicks;
                // 上次没有收到正确的返回帧
                NeedRecvLen = 0;
                return null;
            }

            // 如果写入次数超过三次未成功，则将队列清空
            if (repeatTimes <= 0)
            {
                AlarmFactory.Instance.Insert("Write data error, more than three attempts",
                    AlarmCategory.COMM, Name, 0);
                // 标志位复位 重启下一个批次的读写任务
                WriteFlag = false;
            }
            NeedRecvLen = 0;
            return null;
        }

        /// <summary>
        /// 修改寄存器的值
        /// </summary>
        /// <param name="Index"></param>
        /// <param name="Value"></param>
        public override void PushRegValue(int Index, double Value)
        {
            //寄存器存储顺序从0开始，先是只读存储器，后面是读写存储器

            if (Index >= 0 && (Index < 13))
            {

                if (islogin)
                {
                    writeQueue.Enqueue(new AddressAndVal(Index, Value));
                    WriteFlag = true;
                }
                else {
                    camController = new PTZCamControl(camIp, camPort, camAdmin, camPassword);
                    islogin = camController.login();
                    if (islogin)
                    {
                        RegFactory.Instance.SetVal(RegNameList[11], 0); // 1-step, 0-continue 
                        RegFactory.Instance.SetVal(RegNameList[12], 30); // speed default = 30
                        NeedInit = false;
                        Fail_R = 0;
                    }
                }
            }
            else if (Index == 13)
            {
                if (Value == 1) {
                    camController.login();// 登入
                    NeedInit = false;
                }
                else if (Value == 2)
                {
                    if (camController.logout()) {
                        NeedInit = true;
                    };// 登出
                }                
            }
            else if (Index == 14)
            {
                writeQueue.Clear();// 清空队列
            }
        }
    }
}

